package attori.proattivi;

import gui.houseeditor.HouseModel;
import gui.houseeditor.HouseModel.HouseObject;
import gui.houseeditor.strategies.MinimalisticHouseDrawStrategy.WalkerImage;

import java.util.StringTokenizer;

import sde.actor.Actor;
import sde.actor.Message;
import sde.actor.Timer;

public class Walker extends Actor {

	private static class Timeout extends Message {
	}

	public static class ToIdle extends Message {

	}

	public static class ToOperative extends Message {

	}
	
	public static class AvadaKedavra extends Message{
		
		
	}

	public static class Init extends Message {
		public HouseModel model;
		public String percorso;
		public long periodo;

		public Init(HouseModel model, String percorso, long periodo) {
			super();
			this.model = model;
			this.percorso = percorso;
			this.periodo = periodo;
		}

	}

	private WalkerImage image;
	private HouseModel model;
	private char[] percorso;
	private char[] percorsoOriginale;
	private int lastX;
	private int lastY;
	private int nextMovement;
	public static final byte CREATED = 0, OPERATIVE = 1, IDLE = 2;
	private int contaFermo;

	private Timer timer = new Timer();
	private Timeout timeout = new Timeout();
	private long periodo;

	public Walker() {
		become(CREATED);
	}

	@Override
	protected void handler(Message m) {
		switch (currentStatus()) {
		case CREATED:
			if (m instanceof Init) {
				// System.out.println("Sono nel Walker: "+image);
				model = ((Init) m).model;
				periodo = ((Init) m).periodo;
				StringTokenizer st = new StringTokenizer(((Init) m).percorso,
						":", false);
				String cas = st.nextToken();
				percorso = st.nextToken().toCharArray();
				percorsoOriginale = new char[percorso.length];
				System.arraycopy(percorso, 0, percorsoOriginale, 0,
						percorso.length);
				st = new StringTokenizer(cas, "-", false);
				lastX = Integer.parseInt(st.nextToken());
				lastY = Integer.parseInt(st.nextToken());
				nextMovement = -1;
				become(OPERATIVE);
				timer.set(timeout, this, periodo);
				contaFermo = 0;
			}
			break;
		case OPERATIVE:
			if (m == timeout) {
				muoviti();
				timer.set(m, this, periodo);
			} else if (m instanceof ToIdle) {
				become(IDLE);
			}else if (m instanceof AvadaKedavra){
				destroy();
			}
			break;
		case IDLE:
			if (m instanceof ToOperative) {
				become(OPERATIVE);
				// muoviti();
				timer.set(timeout, this, periodo);
			}else if (m instanceof AvadaKedavra){
				destroy();
			}
			break;
		}
	}

	private void destroy() {
		send(new ToIdle());
		model.setCell(HouseObject.BLANK, lastX, lastY);
	}

	public int getLastX() {
		return lastX;
	}

	public int getLastY() {
		return lastY;
	}


	private void muoviti() {
		if (nextMovement == -1) {
			model.setCell(HouseObject.WALKER, lastX, lastY, image);
			nextMovement++;
		} else {
			char c = percorso[nextMovement];
			switch (c) {
			case 'U':
				if (model.getCell(lastX - 1, lastY) == HouseObject.BLANK) {
					model.setCell(HouseObject.BLANK, lastX, lastY);
					model.setCell(HouseObject.WALKER, lastX - 1, lastY, image);
					lastX--;
					nextMovement = (nextMovement + 1) % (percorso.length - 1);
					if (nextMovement == 0) {
						percorso = new char[percorsoOriginale.length];
						System.arraycopy(percorsoOriginale, 0, percorso, 0,
								percorso.length);
					}
				} else if (contaFermo >= 5) {
					char[] percorsoNew = new char[percorso.length + 2];
					for (int i = 0; i < nextMovement; i++) {
						percorsoNew[i] = percorso[i];
					}
					if (Math.random() > 0.5) {
						percorsoNew[nextMovement] = 'R';
						percorsoNew[nextMovement + 1] = 'L';
					} else {
						percorsoNew[nextMovement] = 'L';
						percorsoNew[nextMovement + 1] = 'R';
					}

					for (int i = nextMovement; i < percorso.length; i++) {
						percorsoNew[i + 2] = percorso[i];
					}
					percorso = percorsoNew;
					contaFermo = 0;

				} else {
					contaFermo++;
				}

				break;
			case 'D':
				if (model.getCell(lastX + 1, lastY) == HouseObject.BLANK) {
					model.setCell(HouseObject.BLANK, lastX, lastY);
					model.setCell(HouseObject.WALKER, lastX + 1, lastY, image);
					lastX++;
					nextMovement = (nextMovement + 1) % (percorso.length - 1);
					if (nextMovement == 0) {
						percorso = new char[percorsoOriginale.length];
						System.arraycopy(percorsoOriginale, 0, percorso, 0,
								percorso.length);
					}
				} else if (contaFermo >= 5) {
					char[] percorsoNew = new char[percorso.length + 2];
					for (int i = 0; i < nextMovement; i++) {
						percorsoNew[i] = percorso[i];
					}
					if (Math.random() > 0.5) {
						percorsoNew[nextMovement] = 'R';
						percorsoNew[nextMovement + 1] = 'L';
					} else {
						percorsoNew[nextMovement] = 'L';
						percorsoNew[nextMovement + 1] = 'R';
					}

					for (int i = nextMovement; i < percorso.length; i++) {
						percorsoNew[i + 2] = percorso[i];
					}
					percorso = percorsoNew;
					contaFermo = 0;
				} else {
					contaFermo++;
				}
				break;
			case 'L':
				if (model.getCell(lastX, lastY - 1) == HouseObject.BLANK) {
					model.setCell(HouseObject.BLANK, lastX, lastY);
					model.setCell(HouseObject.WALKER, lastX, lastY - 1, image);
					lastY--;
					nextMovement = (nextMovement + 1) % (percorso.length - 1);
					if (nextMovement == 0) {
						percorso = new char[percorsoOriginale.length];
						System.arraycopy(percorsoOriginale, 0, percorso, 0,
								percorso.length);
					}
				} else if (contaFermo >= 5) {
					char[] percorsoNew = new char[percorso.length + 2];
					for (int i = 0; i < nextMovement; i++) {
						percorsoNew[i] = percorso[i];
					}
					if (Math.random() > 0.5) {
						percorsoNew[nextMovement] = 'U';
						percorsoNew[nextMovement + 1] = 'D';
					} else {
						percorsoNew[nextMovement] = 'D';
						percorsoNew[nextMovement + 1] = 'U';
					}

					for (int i = nextMovement; i < percorso.length; i++) {
						percorsoNew[i + 2] = percorso[i];
					}
					percorso = percorsoNew;
					contaFermo = 0;
				} else {
					contaFermo++;
				}
				break;
			case 'R':
				if (model.getCell(lastX, lastY + 1) == HouseObject.BLANK) {
					model.setCell(HouseObject.BLANK, lastX, lastY);
					model.setCell(HouseObject.WALKER, lastX, lastY + 1, image);
					lastY++;
					nextMovement = (nextMovement + 1) % (percorso.length - 1);
					if (nextMovement == 0) {
						percorso = new char[percorsoOriginale.length];
						System.arraycopy(percorsoOriginale, 0, percorso, 0,
								percorso.length);
					}
				} else if (contaFermo >= 5) {
					char[] percorsoNew = new char[percorso.length + 2];
					for (int i = 0; i < nextMovement; i++) {
						percorsoNew[i] = percorso[i];
					}
					if (Math.random() > 0.5) {
						percorsoNew[nextMovement] = 'U';
						percorsoNew[nextMovement + 1] = 'D';
					} else {
						percorsoNew[nextMovement] = 'D';
						percorsoNew[nextMovement + 1] = 'U';
					}

					for (int i = nextMovement; i < percorso.length; i++) {
						percorsoNew[i + 2] = percorso[i];
					}
					percorso = percorsoNew;
					contaFermo = 0;
				} else {
					contaFermo++;
				}
				break;

			default:
				break;
			}
		}
	}
}